'use strict';

const Controller = require('../lib/controller');

module.exports = class GbookController extends Controller {
  async index() {
    if (this.ctx.app.theCache.settings.enableGuestBook != 1) {
      // If register is disabled
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        this.ctx.__('gbook_disabled'),
        this.ctx.__('goback'),
        'default.asp',
        false,
        'errorbox'
      );
    }

    switch (String(this.ctx.request.query.act)) {
      case 'save':
        await this.commentSave();
        break;
      case 'edit':
        await this.commentEdit(false);
        break;
      case 'update':
        await this.commentEdit(true);
        break;
      case 'delete':
        await this.commentDelete();
        break;
      default:
        this.ctx.genSecurityCode();
        // View Guestbook
        await this.showGuestBook();
    }

    if (this.ctx.app.inDebug) this.showSQLGB();

  }

  // Output GuestBook ////////////////////////////////////////////////////////////////////////////
  async showGuestBook() {

    let sqlWHERE = '';
    let strURLPrefix = '?';
    let arrKeywords = '';

    // Check current page number
    let pageIndex = this.ctx.helper.checkInt(this.ctx.request.query.page);
    pageIndex = Math.max(1, pageIndex);

    // Check if has search keywords
    if (this.ctx.request.query.q) {
      sqlWHERE += ' WHERE gb_hidden=False';
      arrKeywords = this.ctx.request.query.q.split(' ');
      for (let i = 0; i < this.ctx.request.query.q.length; i++) {
        if (this.ctx.helper.lengthW(arrKeywords[i]) > 2) {
          sqlWHERE += " AND (gb_content LIKE '%" + this.ctx.helper.checkStr(arrKeywords[i]) + "%' OR gb_reply LIKE '%" + this.ctx.helper.checkStr(arrKeywords[i]) + "%')";
        }
      }
      strURLPrefix += strURLPrefix == '?' ? '' : '&amp;';
      strURLPrefix += 'q=' + this.ctx.request.query.q;
    }

    // Check if has highlight keywords
    if (this.ctx.request.query.hl) {
      arrKeywords = this.ctx.request.query.hl.split(' ');
      strURLPrefix += strURLPrefix == '?' ? '' : '&amp;';
      strURLPrefix += 'hl=' + this.ctx.request.query.hl;
    }

    const entryPerPage = this.ctx.app.theCache.settings.entryPerPageGuestBook;
    let entryCount = 0;
    let entries = await this.ctx.app.connBlog.query('SELECT * FROM blog_guestbook' + sqlWHERE + ' ORDER BY gb_postTime DESC', entryPerPage, pageIndex, false);

    if (entries) {
      for (let i = 0; i < entries.length; i++) {
        const arrEntry = { id: entries[i].gb_id,
          userid: entries[i].gb_userid,
          username: entries[i].gb_username,
          content: entries[i].gb_content,
          editMark: entries[i].gb_editmark,
          ubbFlags: entries[i].gb_ubbflags,
          postTime: new Date(entries[i].gb_posttime),
          ip: entries[i].gb_ip,
          reply: entries[i].gb_reply,
          replyTime: new Date(entries[i].gb_replytime),
          replyUsername: entries[i].gb_replyusername,
          hidden: entries[i].gb_hidden };
        entries[i] = '';
        entries[i] = arrEntry;
      }
      entryCount = this.ctx.app.connBlog.recordCount;
    } else {
      entries = '';
      entryCount = 0;
    }

    const data = {
      strTitle: this.ctx.__('guestbook'),
      entries,
      intEntryCount: entryCount,
      intEntryPerPage: entryPerPage,
      intCurrentPage: pageIndex,
      strURLPrefix,
      arrKeywords,
      input: this.ctx.request.query,
    };

    await this.ctx.render('gbook/gbook.ejs', data);
  }

  // Save New Entry //////////////////////////////////////////////////////////////////////////////////
  async commentSave() {
    if (this.ctx.theUser.rights.post < 1 || this.ctx.app.theCache.settings.enableComment == 0 || !this.ctx.session.lbsSecurityCode) {
      // Check User Right - without DB Query
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        this.ctx.__('no_rights'),
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );

    }

    if ((new Date()) - this.ctx.session.FloodControl < this.ctx.app.theCache.settings.minPostDuration * 1000) {
      // Check if user is banned for Spam
      this.ctx.session.FloodControl = new Date();
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        this.ctx.__('flood_control'),
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }

    let strError = '';
    let bCheckCode = true;

    // For guest user group
    if (!this.ctx.theUser.loggedIn) {
      if (this.ctx.request.body.comm_register == 'true') {
        // Do register
        this.ctx.request.body.username = this.ctx.request.body.comm_username;
        this.ctx.request.body.password = this.ctx.request.body.comm_password;
        this.ctx.request.body.repassword = this.ctx.request.body.comm_password;
        this.ctx.request.body.email = '';
        this.ctx.request.body.hideemail = true;
        this.ctx.request.body.scode = this.ctx.request.body.scode;
        const strErrorRegister = await this.ctx.theUser.register(true);
        if (strErrorRegister != false) {
          strError += strErrorRegister;
        } else {
          const tmpA = await this.ctx.app.connBlog.query("SELECT user_id FROM blog_user WHERE user_name='" + this.ctx.helper.checkStr(this.ctx.request.query.comm_username) + "'");
          if (tmpA && tmpA.length) {
            this.ctx.theUser.id = tmpA[0].user_id;
          }
        }
        bCheckCode = false; // Bypass the Security Code check below
      } else if (this.ctx.request.body.comm_password !== undefined && this.ctx.request.body.comm_password !== '') {
        // Do login
        const strErrorLogin = await this.ctx.theUser.login(
          this.ctx.request.body.comm_username,
          this.ctx.request.body.comm_password,
          1,
          true,
          this.ctx.request.body.scode
        );
        if (strErrorLogin != false) {
          strError += strErrorLogin;
        }
        bCheckCode = false; // Bypass the Security Code check below
      } else {
        // Check Username for Guest
        if (!this.ctx.request.body.comm_username || !this.ctx.helper.checkUsername(this.ctx.request.body.comm_username)) {
          strError += '<li>' + lang.username_invalid + '</li>';
        } else if (await this.ctx.app.connBlog.query("SELECT user_id FROM blog_user WHERE user_name='" + this.ctx.helper.checkStr(this.ctx.request.body.comm_username) + "'")) {
          strError += '<li>' + lang.user_exist + '</li>';
        }
        this.ctx.theUser.id = 0;
        this.ctx.theUser.username = this.ctx.request.body.comm_username;
      }
    }

    // Check for data
    strError += this.checkPostData(bCheckCode);

    // Check for ubbFlags
    const strUbbFlags = this.getUbbFlags();

    if (strError != '') {
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        strError,
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }

    const arrInsert = {
      gb_content: this.ctx.request.body.message,
      gb_userid: this.ctx.theUser.id,
      gb_username: this.ctx.theUser.username,
      gb_ubbFlags: strUbbFlags,
      gb_hidden: this.ctx.request.body.comm_hidden == 'true',
      gb_postTime: new Date(),
      gb_ip: this.ctx.theUser.IP,
    };
    await this.ctx.app.connBlog.insert('guestbook', arrInsert);

    // Clean up to avoid abuse
    this.ctx.session.lbsSecurityCode = null;

    // Flood Control
    this.ctx.session.FloodControl = new Date();

    // Output ok message
    return await this.ctx.response.redirectMessage(
      this.ctx.__('done'),
      this.ctx.__('comment_save_done'),
      this.ctx.__('redirect'),
      '?',
      true,
      'messagebox'
    );
  }

  // Check Post Form Data -----------------------
  async checkPostData(bCheckCode) {

    let strError = '';

    // Check Security Code
    if (this.ctx.app.theCache.settings.enableSecurityCode == 1
      && bCheckCode
      && this.ctx.session.lbsSecurityCode != this.ctx.request.query.scode) {
      strError += '<li>' + this.ctx.__('scode_invalid') + '</li>';
    }

    // Workaround for content/reply swap when the user has reply rights
    if (this.ctx.request.body.entry) {
      this.ctx.request.body.reply = this.ctx.request.body.message;
      this.ctx.request.body.message = this.ctx.request.body.entry;
      if (this.ctx.request.body.reply.length > this.ctx.app.theCache.settings.maxCommentLength || this.ctx.request.body.reply.length < 2) {
        strError += '<li>' + this.ctx.__('length_invalid') + '</li>';
      }
    }
    // Check content
    this.ctx.request.body.message = this.ctx.helper.trim(this.ctx.request.body.message);
    if (!this.ctx.request.body.message) {
      strError += '<li>' + this.ctx.__('content_blank') + '</li>';
    } else {
      if (this.ctx.request.body.message.length > this.ctx.app.theCache.settings.maxCommentLength || this.ctx.request.body.message.length < 2) {
        strError += '<li>' + this.ctx.__('length_invalid') + '</li>';
      }
      if (this.ctx.helper.countURL(this.ctx.request.body.message) > this.ctx.app.theCache.settings.maxCommentURLCount) {
        strError += '<li>' + this.ctx.__('comment_url_count_block') + '</li>';
      }
      this.ctx.request.body.message = this.ctx.helper.wordFilter(this.ctx.request.body.message);
      if (!this.ctx.request.body.message) {
        strError += '<li>' + this.ctx.__('wordfilter_block') + '</li>';
      }
    }

    return strError;

  }

  // Get ubbFlags String -----------------------
  async getUbbFlags() {
    let ubbFlags = '';
    ubbFlags += this.ctx.request.body.e_ubb == 'true' ? '1' : '0';
    ubbFlags += this.ctx.request.body.e_autourl == 'true' ? '1' : '0';
    ubbFlags += '2'; // bImage - always 2
    ubbFlags += '2'; // bMedia - always 2
    ubbFlags += this.ctx.request.body.e_smilies == 'true' ? '1' : '0';
    ubbFlags += '1'; // bTextBlock - always 1
    return ubbFlags;
  }

  // Edit Entry ///////////////////////////////////////////////////////////////////////////////////
  async commentEdit(bSave) {
    if (this.ctx.theUser.rights.edit < 1) {
      // Check User Right - without DB Query
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        this.ctx.__('no_rights'),
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }

    let strError = '';
    let arrData;

    this.ctx.request.query.id = this.ctx.helper.checkInt(this.ctx.request.query.id);
    if (!this.ctx.request.query.id) {
      strError = this.ctx.__('invalid_parameter');
    } else {
      // Check user right again
      arrData = await this.ctx.app.connBlog.query('SELECT gb_userid,gb_content,gb_reply,gb_ubbFlags,gb_hidden FROM blog_guestbook WHERE gb_id=' + this.ctx.request.query.id, 1, 1);
      if (arrData) {
        arrData = arrData[0];
        if (this.ctx.theUser.id != arrData.gb_userid && this.ctx.theUser.rights.edit < 2) {
          strError = this.ctx.__('no_rights');
        }
      } else {
        strError = this.ctx.__('comment_not_found');
      }
    }

    if (strError != '') {
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        strError,
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }

    if (!bSave) {
      // Output the Edit Form
      this.ctx.genSecurityCode();

      const data = {
        strTitle: this.ctx.__('edit_gbook_entry'),
        strActionURL: '?act=update&id=' + this.ctx.request.query.id,
        strContent: arrData.gb_content,
        strUBBFlags: arrData.gb_ubbflags,
        bHidden: arrData.gb_hidden,
        strReply: arrData.gb_reply,
        bShowReplyArea: this.ctx.theUser.rights.edit > 2,
      };
      return await this.ctx.render('gbook/editEntry.ejs', data);

    }

    // Save changes
    strError = this.checkPostData(true);
    const strUbbFlags = this.getUbbFlags();

    if (strError != '') {
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        strError,
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }
    const arrUpdate = {
      gb_content: this.ctx.request.body.message,
      gb_ubbFlags: strUbbFlags,
      gb_hidden: this.ctx.request.body.comm_hidden == 'true',
    };
    if (this.ctx.request.body.message != arrData.gb_content) {
      arrUpdate.gb_editMark = this.ctx.theUser.username + '$|$' + this.ctx.helper.getDateTimeString();
    }

    // If the user has reply rights
    if (this.ctx.theUser.rights.edit > 1) {
      arrUpdate.gb_reply = this.ctx.request.body.reply;
      arrUpdate.gb_replyUsername = this.ctx.theUser.username;
      arrUpdate.gb_replyTime = new Date();
    }

    await this.ctx.app.connBlog.update('blog_guestbook', arrUpdate, 'gb_id=' + this.ctx.request.query.id);

    // Clean up to avoid abuse
    this.ctx.session.lbsSecurityCode = null;
    // Output ok message
    await this.ctx.response.redirectMessage(
      this.ctx.__('done'),
      this.ctx.__('comment_save_done'),
      this.ctx.__('redirect'),
      '?',
      true,
      'messagebox'
    );
  }

  // Delete Comment /////////////////////////////////////////////////////////////////////////////
  async commentDelete() {
    if (this.ctx.theUser.rights.delete < 1) {
      // Check User Right - without DB Query
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        this.ctx.__('no_rights'),
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }

    let strError = '';

    this.ctx.request.query.id = this.ctx.helper.checkInt(this.ctx.request.query.id);
    if (!this.ctx.request.query.id) {
      strError = this.ctx.__('invalid_parameter');
    } else {
      // Check user right again
      let arrData = await this.ctx.app.connBlog.query('SELECT gb_userid FROM blog_guestbook WHERE gb_id=' + this.ctx.request.query.id, 1, 1);
      if (arrData) {
        arrData = arrData[0];
        if (this.ctx.theUser.id != arrData.gb_userid
          && this.ctx.theUser.groupID != 1
          && this.ctx.theUser.rights.delete < 2) {
          strError = this.ctx.__('no_rights');
        }
      } else {
        strError = this.ctx.__('comment_not_found');
      }

      if (strError != '') {
        return await this.ctx.response.redirectMessage(
          this.ctx.__('error'),
          strError,
          this.ctx.__('goback'),
          'javascript:window.history.back();',
          false,
          'errorbox'
        );
      }

      await this.ctx.app.connBlog.doDelete('blog_guestbook', 'gb_id=' + this.ctx.request.query.id);

      await this.ctx.response.redirectMessage(
        this.ctx.__('done'),
        this.ctx.__('comment_delete_done'),
        this.ctx.__('redirect'),
        '?',
        true,
        'messagebox'
      );

    }
  }

  // SQL Debug Output for GBook
  async showSQLGB() {

    let str = 'SQLGB:\n';
    str += 'SQL: ' + this.ctx.app.connBlog.queryCount + ' queries\tReturn\tTotal\n';
    for (let i = 0; i < this.ctx.app.connBlog.debugData.length; i++) {
      str += '\t' + this.ctx.app.connBlog.debugData[i][0] + '\t' + this.ctx.app.connBlog.debugData[i][1] + '\n' + this.ctx.app.connBlog.debugData[i][2] + '';
    }
    str += '\n';

    this.ctx.logger.debug(str);
  }
};
